import json
import pickle
import threading

from PySide6.QtCore import Qt
from PySide6.QtWidgets import QTableWidgetItem

from ikuai import IKuai
from toutiao import Toutiao
from utils import *
import time


# 魔云腾安卓容器API
class AndroidDockerApi:
    def __init__(self, server_ips, super_sdk_api):
        # ip数组要求格式：ip:端口
        self.server_ips = server_ips
        # 超级SDK接口地址
        self.api = HttpApi(super_sdk_api)
        # 安卓ip字典
        self.android_list = {}
        self.set_custom_count = 0
        self.table_count = 0
        self.l2tp = {}
        self.install = {
            "tt": False,
            "js": False,
            'dy': False,
            'dy_lite': False
        }
        DkGlobal().android_docker = self
        pass

    def start_android(self):
        win_log("初始化....")
        self.iKuai = IKuai()
        # 获取设备信息
        self.get_android_list()
        android_list = self.load_task()
        print("load_", android_list)
        for android in android_list.values():
            self.android_list[android['ip']]['task'] = android['task']
            print("self.android_list[android['ip']]", self.android_list)
            if "install" in self.android_list[android['ip']]:
                self.install = self.android_list[android['ip']]['install']
        self.save_task()
        # 保持Ikuai
        ikuai_thread = threading.Thread(target=self.iKuai.latp_keep)
        ikuai_thread.start()
        # 初始化IKuai
        # 获取设备列表
        while DkGlobal().window.running:
            if DkGlobal().body.bodyRunning:
                for android in self.android_list.values():
                    # 这里for里面是不是每个要等里面的任务陆续完成后才进行下一次的循环？
                    if (android['status'] == "wait" and android['switch'] == True):
                        thread = threading.Thread(target=self.task_start, args=(android,))
                        thread.start()
                time.sleep(3)
            else:
                time.sleep(5)

    def task_start_test(self, android):
        self.set_android_status(android, '重置设备')
        self.refresh_android(android)
        self.set_android_status(android, '重置结束')
        devinfo = ServerApi().get_devinfo()
        self.set_android_status(android, 'run')
        self.handle_install(android, devinfo['app_number'])
        # if android['task']:
        #     print("当前已经有任务不重启", android)
        # print("android", android)
        # time.sleep(3)
        # self.set_android_status(android, '重启中')
        # time.sleep(5)
        # win_log('测试内容', '', android['Name'])
        # self.add_android_count(android)
        # time.sleep(5)
        # self.set_android_status(android, 'wait')
        pass

    # 执行点击ad操作
    def task_start(self, android):
        self.set_android_status(android, 'run')
        ###################################重置设备#######################################
        if android['task'] is None:
            self.set_android_status(android, '重置设备')
            self.refresh_android(android)
            self.set_android_status(android, '重置结束')
            #####################################################安装程序######################
            self.time_sleep(android, 5)
            win_log('准备获取小程序Appid和真机信息')
            devinfo = ServerApi().get_devinfo()
            if devinfo == 0:
                win_log("当前已无小程序任务", 'error', android['Name'])
                DkGlobal().body.bodyRunning = False
                return False
            win_log(f'获取到Appid：{devinfo["appid"]}, 应用：{devinfo["app_name"]}')
            self.set_android_status(android, '写真机信息')
            devinfo = self.set_custom_devinfo_force(android, devinfo)
            if devinfo == False:
                win_log(f"{android['Name']}真机信息失败次数太多,准备重启", 'error', android['Name'])
                self.set_android_status(android, 'wait')
                return False
            time.sleep(5)
        else:
            print("已经有了数据了")
            devinfo = android['task']['devinfo']
        ############################################## 执行APP操作 ##################################
        if devinfo != None:
            self.handle_install(android, devinfo['app_number'])
        #     while True:
        #         # 移除当前真机信息数据
        #         if "content" in devinfo:
        #             del devinfo['content']
        #         self.set_table_item(android, 3, devinfo['app_name'])
        #         toutiao = Toutiao(android, devinfo)
        #         res = toutiao.mytapi.check_connect_state()
        #         if res == True:
        #             # # 重拨IP vpn_id和IP绑定
        #             self.set_android_status(android, '刷新IP')
        #             win_log(f"准备重拨设备{android['Name']}的IP地址", '', android['Name'])
        #             self.iKuai.refresh_ip(android)
        #             self.set_android_status(android, '刷新IP成功')
        #             toutiao.start()
        #             break
        #         else:
        #             self.restart_android(android)
        #             self.time_sleep(android, 10)
        #             win_log("连接RPC失败-重启设备", 'error', android['Name'])
        #
        #     # 更新执行次数
        #     self.add_android_count(android)
        # self.set_android_status(android, 'wait')
        if DkGlobal().window.running == False:
            win_log(f"设备{android['Name']}已结束运行")

    def handle_install(self, android, app_number):
        app_type_name = {1: 'js', 2: 'tt', 3: 'dy', 4: 'dy_lite'}
        for type in app_number:
            name = app_type_name[int(type)]
            print(f"{android['Name']}安装应用{name},安装状态：{self.install[name]},应用次数为：{app_number[type]},app_number:{app_number}")
            if self.install[name] == False and app_number[type] > 0:
                self.time_sleep(android, 2)
                self.set_android_status(android, f'安装{name}')
                res = self.install_apk(android, name)
                if res == True:
                    self.set_android_status(android, f'安装{name}完毕')
                    self.install[name] = True
                    self.android_list[android['ip']]['install'] = self.install
                else:
                    self.set_android_status(android, f'安装{name}失败')
        self.set_android_status(android, "安装成功")

    def set_android_status(self, android, status):
        if DkGlobal().body != None:
            self.android_list[android['ip']]['status'] = status
            keys = list(self.android_list.keys())
            row = keys.index(android['ip'])
            item = QTableWidgetItem(str(status))  # 将数据转换成字符串形式
            item.setTextAlignment(Qt.AlignCenter)
            DkGlobal().body.tableWidget.setItem(row, 6, item)

    def add_android_count(self, android):
        if DkGlobal().body != None:
            self.android_list[android['ip']]['run_count'] += 1
            keys = list(self.android_list.keys())
            row = keys.index(android['ip'])
            item = QTableWidgetItem(str(self.android_list[android['ip']]['run_count']))  # 将数据转换成字符串形式
            item.setTextAlignment(Qt.AlignCenter)
            DkGlobal().body.tableWidget.setItem(row, 4, item)
            self.save_task()

    # 重启设备
    def restart_android(self, android):
        res = self.api.get(f"/reboot/{android['SERVER_IP']}/{android['Names']}")
        res = json.loads(res.content)
        if res['code'] == 200:
            win_log(f"重启设备{android['Name']} 成功")
            return True
        else:
            win_log(f"重启设备{android['Name']} 失败", 'error')
            return False

    # 重置设备
    def reset_android(self, android):
        res = self.api.get(f"/reset/{android['SERVER_IP']}/{android['Names']}")
        res = json.loads(res.content)
        if res['code'] == 200:
            win_log(f"重置设备{android['Name']} 成功")
            return True
        else:
            win_log(f"重置设备{android['Name']} 失败", 'error')
            return False

    def run_android(self, android):
        res = self.api.get(f"/run/{android['SERVER_IP']}/{android['Names']}")
        res = json.loads(res.content)
        if res['code'] == 200:
            win_log(f"启动{android['Name']} 成功")
            return True
        else:
            win_log(f"启动{android['Name']} 失败", 'error')
            return False

    # / get_android_boot_status / {ip} / {name}
    def get_android_boot_status(self, android):
        res = self.api.get(f"/get_android_boot_status/{android['SERVER_IP']}/{android['Names']}")
        res = json.loads(res.content)
        print(res)
        if res['code'] == 200:
            win_log(f"启动{android['Name']} 成功")
            return True
        else:
            win_log(f"{android['Name']} 启动中", '', android['Name'])
            return False

    # 重置安卓设备
    def refresh_android(self, android):
        res = self.reset_android(android)
        print(res)
        if res == False:
            return False
        self.time_sleep(android, 2)
        res = self.run_android(android)
        if res == False:
            return False
        times = 0
        while True:
            res = self.get_android_boot_status(android)
            self.time_sleep(android, 10)
            times += 10
            if times >= 30:
                self.set_android_status(android, '重置中')
                print(f"当前等待：{times}秒 ，res:{res}", 'error', android['Name'])
            if res:
                self.set_android_status(android, "重置成功")
                return True

    def install_apk(self, android, name='js', count=0):
        if count > 10:
            win_log(f"安装{name}--{android['Name']}超出次数", 'error', android['Name'])
            return False
        self.set_android_status(android, f"安装{name}第{count}次")
        res = self.api.get(f"/install_apk/{android['SERVER_IP']}/{android['Names']}?local=C:/apk/{name}.apk")
        res = json.loads(res.content)
        if res['code'] == 0:
            win_log(f"{android['Name']} 安装 - {name} 成功")
            return True
        else:
            win_log(f"安装{android['Name']} 失败 {res['msg']}", 'error')
            self.install_apk(android, name, count + 1)
            self.time_sleep(android, 7)

    # 强制写入真机信息
    def set_custom_devinfo_force(self, android, devinfo):
        if self.set_custom_count >= 3:
            win_log("写真机信息超出次数", 'error')
            self.set_custom_count = 0
            return False
        count = 0
        while True:
            if count >= 3:
                break
            self.iKuai.refresh_ip(android, True, True)
            win_log(f"{android['Name']}因写真机信息刷新IP,重写测试", 'error')
            dev_info_res = self.set_custom_devinfo(android, devinfo['content'])
            if dev_info_res == True:
                return devinfo
            else:
                self.time_sleep(android, 5)
                count += 1

        ServerApi().set_devinfo_error_count(devinfo['devinfo_id'])
        win_log(f"写入真机信息失败，ID:{devinfo['devinfo_id']}", 'error')
        new_devinfo = ServerApi().get_new_devinfo(devinfo['auto_id'])
        if new_devinfo != None:
            devinfo['content'] = new_devinfo['content']
            devinfo['devinfo_id'] = new_devinfo['id']
            self.set_custom_count += 1
            self.iKuai.refresh_ip(android)
            self.time_sleep(android, 4)
            self.set_custom_devinfo_force(android, devinfo)

    # 真机信息
    def set_custom_devinfo(self, android, content):
        try:
            # 发送请求
            res = self.api.post(f"set_custom_devinfo/{android['SERVER_IP']}/{android['Names']}", None, content)
            # 检查响应状态码
            if res.status_code == 200:
                # 尝试解析 JSON
                response_data = json.loads(res.content)

                # 检查解析结果
                if 'code' in response_data:
                    if response_data['code'] == 200:
                        win_log(f"{android['Name']}写入真机信息成功")
                        return True
                    else:
                        win_log(f"{android['Name']}写入真机信息失败: {response_data.get('msg', '')}", 'error')
                        return False
                else:
                    win_log(f"{android['Name']}写入真机信息失败: 无效的响应数据", 'error')
                    return False
            else:
                win_log(f"{android['Name']}写入真机信息失败: 请求失败，状态码 {res.status_code}", 'error')
                return False

        except json.JSONDecodeError as e:
            win_log(f"{android['Name']}写入真机信息失败: 响应不是有效的 JSON 格式: {str(e)}", 'error')
            return False
        except Exception as e:
            win_log(f"{android['Name']}写入真机信息失败: 未知错误: {str(e)}", 'error')
            return False

    def update_table(self):
        table_data = []
        for item in self.android_list.values():
            task = item['task']
            # 这里修改统计
            table_data.append([
                item['Name'],  # 设备名称
                task['progress'] if task else '-',  # 进度
                item['ip'],  # IP
                task['app_name'] if task else '-',  # 小程序名
                item['run_count'],  # 轮次
                task['app_type'] if task else '1',  # 当前执行类型
                item['status'],  # 状态
                item['wait_time'],  # 倒计时
                item['switch']  # 开关
            ])
            if DkGlobal().body:
                DkGlobal().body.populate_table(table_data)

    def get_android_list(self):
        win_log("开始获取安卓设备.....")
        ip_item_list = IKuai().get_ip_item_list()
        print("ip_item_list", ip_item_list)
        # try:
        for server_ip in self.server_ips:
            print("server_ips", self.server_ips)
            # 切分ip地址
            ip = server_ip.split(':')[0]
            print(server_ip)
            http_url = "http://" + server_ip
            android_res = self.api.get("get/" + ip)
            print("android", json.loads(android_res.text))
            # JSON 转字典
            android_data = json.loads(android_res.text)
            if android_data['code'] == 200:
                win_log(f"主机{ip} 获取设备信息成功")
                print("android_data", android_data['msg'])
                for item in android_data['msg']:
                    if item['State'] != 'running':
                        continue
                    android_api_res = self.api.get(f"/get_api_info/{ip}/{item['Names']}")
                    android_api_data = json.loads(android_api_res.text)
                    if android_api_data['code'] == 200:
                        item.update(android_api_data['msg'])
                    else:
                        win_log(f"获取设备{item['ip']} 获取信息失败")
                        # 获取API报错逻辑
                        pass
                    # 最终item格式为：
                    item['SERVER_IP'] = server_ip.split(':')[0]
                    item['SERVER_PORT'] = server_ip.split(':')[1]
                    item['SERVER_HTTP'] = http_url
                    # 设备简化名
                    item['Name'] = item['Names'][35:]
                    #################################下面是自定义的字段###################
                    # 状态
                    item['status'] = 'wait'
                    # 等待时间
                    item['wait_time'] = 0
                    # 使用
                    item['switch'] = True
                    # 运行次数
                    item['run_count'] = 0
                    # 任务信息
                    item['task'] = None
                    if ip_item_list.get(item['ip']) is not None:
                        item['l2tp'] = ip_item_list[item['ip']]  # ip信息
                    else:
                        win_log(f"设备{item['Name']} 没有配置动态IP", 'error')
                        item['l2tp'] = None

                    win_log(f"获取设备{item['Name']} 获取信息成功")

                    self.android_list[item['ip']] = item
                    # 这里设置实例
                    self.update_table()
                return True
            else:
                # 这里写报错的逻辑
                win_log(f"主机{ip} 获取设备信息失败", 'error')
                return False

    # 保存任务
    def save_task(self):
        print("保存任务数据")
        log_file_path = os.path.join('log', 'task.json')
        print("save_task", self.android_list)
        try:
            with open(log_file_path, 'w', encoding='utf-8') as file:
                json.dump(self.android_list, file, ensure_ascii=False, indent=4)
                print("保存任务成功")
        except Exception as e:
            print("保存任务失败{e}")

    def load_task(self):
        log_file_path = os.path.join('log', 'task.json')
        try:
            with open(log_file_path, 'r', encoding='utf-8') as file:
                android_list = json.load(file)
            return android_list
        except Exception as e:
            print(f"当前没有保存的任务{e}")
            return {}

    # 读取任务
    def get_task(self):
        pass

    def time_sleep(self, android, _time):
        while True:
            if _time <= 0:
                break
            time.sleep(1)
            _time -= 1
            self.set_table_item(android, 7, _time)

    def set_table_item(self, android, role, item):
        if DkGlobal().body != None:
            self.app_type = item
            keys = list(self.android_list.keys())
            row = keys.index(android['ip'])
            item = QTableWidgetItem(str(item))
            item.setTextAlignment(Qt.AlignCenter)
            DkGlobal().body.tableWidget.setItem(row, role, item)


if __name__ == '__main__':
    self = AndroidDockerApi(["192.168.9.101:83"], "http://127.0.0.1:5000")
    # self.get_android_list()
    # self.save_task()
    # print(self.load_task()['192.168.9.102'])
    # self = AndroidDockerApi("192.168.9.101:83", "http://127.0.0.1:5000")
    android = getTestAndroid(4)
    # self.install_apk(android, 'dy')
    res = self.get_android_list()
    print('res111',res)
    # self.install_apk(android, 'js')
    # self.refresh_android(android)
    # res = self.refresh_android(android)
    # print(res)
    # ikuai = IKuai()
    # print("android",android)
    # ikuai.refresh_ip(android,True)
    # print('l2tp_data',ikuai.l2tp_data)
    # res = ikuai.get_ip_id_list()
    # res = ikuai.get_iface_check(android['l2tp_id'])
